/*
 * The contents of this file are subject to the Mozilla Public License
 * Version 1.1 (the "License"); you may not use this file except in
 * compliance with the License. You may obtain a copy of the License at
 * http://www.mozilla.org/MPL/
 *
 * Software distributed under the License is distributed on an "AS IS"
 * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the
 * License for the specific language governing rights and limitations
 * under the License.
 * 
 * The Original Code is iSQL-Viewer, A Mutli-Platform Database Tool.
 *
 * The Initial Developer of the Original Code is iSQL-Viewer, A Mutli-Platform Database Tool.
 * Portions created by Mark A. Kobold are Copyright (C) 2000-2007. All Rights Reserved.
 *
 * Contributor(s): 
 *  Mark A. Kobold [mkobold <at> isqlviewer <dot> com].
 *  
 * If you didn't download this code from the following link, you should check
 * if you aren't using an obsolete version: http://www.isqlviewer.com
 */
package org.isqlviewer.ui.dnd;

import java.awt.Component;
import java.awt.datatransfer.DataFlavor;
import java.awt.datatransfer.Transferable;
import java.awt.datatransfer.UnsupportedFlavorException;
import java.awt.dnd.DnDConstants;
import java.awt.dnd.DropTargetDragEvent;
import java.awt.dnd.DropTargetDropEvent;
import java.awt.dnd.DropTargetEvent;
import java.awt.dnd.DropTargetListener;
import java.awt.event.ActionEvent;
import java.io.IOException;
import java.text.MessageFormat;

import org.isqlviewer.bookmarks.Bookmark;
import org.isqlviewer.history.HistoricalCommand;
import org.isqlviewer.model.JdbcSchemaTreeModel;
import org.isqlviewer.model.SchemaNode;
import org.isqlviewer.swing.action.SharedActions;
import org.isqlviewer.swing.action.SwingEventManager;
import org.isqlviewer.ui.TabbedResultsetRenderer;

/**
 * Adapter object for handling drop events for things the generate result sets from the connected service.
 * <p>
 * 
 * @author Mark A. Kobold &lt;mkobold at isqlviewer dot com&gt;
 * @version 1.0
 */
public class ResultSetRendererDropTarget implements DropTargetListener {

    private static final long serialVersionUID = 1941372297753703481L;
    private static DataFlavor[] supportedFlavors = new DataFlavor[]{
            SchemaNode.DATA_FLAVOR, Bookmark.BOOKMARK_FLAVOR, HistoricalCommand.FLAVOR, DataFlavor.stringFlavor};
    private TabbedResultsetRenderer nodeRenderer = null;
    private JdbcSchemaTreeModel treeModel = null;
    private SwingEventManager eventManager = null;

    public void setEventManager(SwingEventManager eventManager) {

        this.eventManager = eventManager;
    }

    public void setNodeRenderer(TabbedResultsetRenderer nodeRenderer) {

        this.nodeRenderer = nodeRenderer;
    }

    public void setTreeModel(JdbcSchemaTreeModel treeModel) {

        this.treeModel = treeModel;
    }

    public synchronized void dragEnter(DropTargetDragEvent event) {

        Transferable transferrable = event.getTransferable();
        if (!isDataFlavorSupported(transferrable)) {
            event.rejectDrag();
        }
    }

    public synchronized void dragExit(DropTargetEvent event) {

    }

    public void dragOver(DropTargetDragEvent event) {

    }

    public void dropActionChanged(DropTargetDragEvent dtde) {

    }

    public void drop(DropTargetDropEvent event) {

        Transferable transferrable = event.getTransferable();
        int dropAction = event.getDropAction();

        if (transferrable.isDataFlavorSupported(Bookmark.BOOKMARK_FLAVOR)) {
            Bookmark command;
            try {
                command = (Bookmark) transferrable.getTransferData(Bookmark.BOOKMARK_FLAVOR);
                String sql = command.getCommandText();
                int eventId = SharedActions.EXECUTE_SQL_COMMAND;
                ActionEvent executeAction = new ActionEvent(this, eventId, sql);
                eventManager.actionPerformed(executeAction);
                event.acceptDrop(dropAction);
            } catch (UnsupportedFlavorException ignored) {
                // we call isDataFlavorSupported() so we should be good//
                event.rejectDrop();
                return;
            } catch (IOException e) {
                event.rejectDrop();
                return;
            }
        } else if (transferrable.isDataFlavorSupported(HistoricalCommand.FLAVOR)) {
            HistoricalCommand command;
            try {
                command = (HistoricalCommand) transferrable.getTransferData(HistoricalCommand.FLAVOR);
                String sql = command.getCommandText();
                int eventId = SharedActions.EXECUTE_SQL_COMMAND;
                ActionEvent executeAction = new ActionEvent(this, eventId, sql);
                eventManager.actionPerformed(executeAction);
                event.acceptDrop(dropAction);
            } catch (UnsupportedFlavorException ignored) {
                // we call isDataFlavorSupported() so we should be good//
                event.rejectDrop();
                return;
            } catch (IOException e) {
                event.rejectDrop();
                return;
            }
        } else if (transferrable.isDataFlavorSupported(SchemaNode.DATA_FLAVOR)) {
            SchemaNode schemaNode;
            try {
                schemaNode = (SchemaNode) transferrable.getTransferData(SchemaNode.DATA_FLAVOR);
                event.acceptDrop(dropAction);
            } catch (UnsupportedFlavorException ignored) {
                // we call isDataFlavorSupported() so we should be good//
                event.rejectDrop();
                return;
            } catch (IOException e) {
                event.rejectDrop();
                return;
            }
            switch (dropAction) {
                case DnDConstants.ACTION_MOVE :
                    renderSchemNode(schemaNode);
                    break;
                case DnDConstants.ACTION_COPY :
                    String sql = constructQueryForNode(schemaNode);
                    if (sql != null) {
                        int eventId = SharedActions.EXECUTE_SQL_COMMAND;
                        ActionEvent executeAction = new ActionEvent(this, eventId, sql);
                        eventManager.actionPerformed(executeAction);
                    }
                    break;
                default :
                    break;
            }
        }
    }

    public Component getComponent() {

        return nodeRenderer.getTabbedPane();
    }

    private void renderSchemNode(SchemaNode schemaNode) {

        Runnable renderer = new SchemaNodeRenderer(nodeRenderer, treeModel, getComponent(), schemaNode);
        eventManager.enqueueRunnable(renderer);
    }

    private boolean isDataFlavorSupported(Transferable flavor) {

        for (int i = 0; i < supportedFlavors.length; i++) {
            if (flavor.isDataFlavorSupported(supportedFlavors[i])) {
                return true;
            }
        }
        return false;
    }

    private String constructQueryForNode(SchemaNode schemaNode) {

        Object[] arguments = null;
        switch (schemaNode.getNodeType()) {
            case PRIMARY_KEYS :
                break;
            case TABLE :
                arguments = new Object[1];
                arguments[0] = schemaNode.getUserObject();
                return MessageFormat.format("SELECT * FROM {0}", arguments);
            case COLUMN_SET :
                arguments = new Object[1];
                arguments[0] = ((SchemaNode) schemaNode.getParent()).getUserObject();
                return MessageFormat.format("SELECT * FROM {0}", arguments);
            case COLUMN :
                arguments = new Object[2];
                arguments[0] = schemaNode.getUserObject();
                arguments[1] = ((SchemaNode) schemaNode.getParent().getParent()).getUserObject();
                return MessageFormat.format("SELECT {0} FROM {1}", arguments);
            default :
                break;

        }
        return null;
    }

}
